use crate::{db, service};
use wanmesh_common::error::{ErrorBacktrace, ResponseError, ResponseErrorAny};

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("{0}")]
    ResponseError(#[from] ResponseError),
    #[error("{0}")]
    ResponseErrorAny(#[from] ResponseErrorAny),
    #[error("{0}")]
    ObjectHasBeenReferenceError(#[from] ObjectHasBeenReferenceError),
    #[error("{0}")]
    DbError(#[from] db::DbErr),
    #[error("{0}")]
    Other(#[from] anyhow::Error),
}

impl From<service::Error> for Error {
    fn from(value: service::Error) -> Self {
        match value {
            service::Error::ResponseError(e) => Error::ResponseError(e),
            service::Error::ResponseErrorAny(e) => Error::ResponseErrorAny(e),
            service::Error::DbError(e) => Error::DbError(e),
            service::Error::Other(e) => Error::Other(e),
        }
    }
}

#[derive(thiserror::Error, Debug)]
#[error("对象已被{object_name}引用，{message}\n{backtrace}")]
pub struct ObjectHasBeenReferenceError {
    pub object_name: String,
    pub message: String,
    pub backtrace: ErrorBacktrace,
}

impl ObjectHasBeenReferenceError {
    pub fn endpoint_peer(endpoint_peer_id: &str) -> Self {
        ObjectHasBeenReferenceError {
            object_name: "endpoint_peer".to_string(),
            message: format!("endpoint_peer_id={}", endpoint_peer_id),
            backtrace: Default::default(),
        }
    }
    pub fn candidate_path(candidate_path_id: &str) -> Self {
        ObjectHasBeenReferenceError {
            object_name: "candidate_path".to_string(),
            message: format!("candidate_path_id={}", candidate_path_id),
            backtrace: Default::default(),
        }
    }

    pub fn traffic_steering_rule(traffic_steering_rule_id: &str) -> Self {
        ObjectHasBeenReferenceError {
            object_name: "traffic_steering_rule".to_string(),
            message: format!("traffic_steering_rule_id={}", traffic_steering_rule_id),
            backtrace: Default::default(),
        }
    }
}
